﻿using AutoCommunication.Enums;
using AutoCommunication.Helper;
using System;
using System.Threading.Tasks;

namespace AutoCommunication.Base
{
    public interface IDevice2
    {

        #region Events

        /// <summary>
        /// 报警将激发的事件
        /// </summary>
        event Action<BaseVariable, AlarmEventArgs> Alarmer;

        /// <summary>
        /// 当变量的值发生改变后,执行通知的事件
        /// </summary>
        event Action<BaseVariable> DataChange;

        /// <summary>
        /// 连接成功
        /// </summary>
        public event Action<string, bool> EventConnect;

        /// <summary>
        /// 断开连接
        /// </summary>
        public event Action<string> EventDisConnect;

        #endregion Events

        #region Properties

        /// <summary>
        /// 分批缓冲区大小
        /// </summary>
        int BufferSize { get; set; }

        /// <summary>
        /// 当前设备是否是连接的,设备不同,判断方式不同,需要重写
        /// 决定统一采用,通过判断多少次读取不到数据,认定为false
        /// </summary>
        bool Connected { get; set; }

        /// <summary>
        /// 通讯周期:也就是读取一次全部变量花的时间
        /// </summary>
        double? CycleTime { get; set; }

        /// <summary>
        /// 变量描述
        /// </summary>
        string Description { get; set; }

        /// <summary>
        /// 是否采用多组读取,快速读取,主要是还有一些设备没有实现,还有些设备可能会有Bug
        /// </summary>
        bool FastRead { get; set; }

        /// <summary>
        /// 设备大小端
        /// </summary>
        EndianFormat Format { get; set; }

        /// <summary>
        /// 是否激活,默认为true
        /// </summary>
        bool IsActive { get; set; }

        /// <summary>
        /// 是否是第一次连接,用于判断重连是否等待
        /// </summary>
        bool IsFirstConnect { get; set; }

        /// <summary>
        /// 表示设备参数,变量参数等是否全部符合,全部符合为true
        /// </summary>
        bool IsReady { get; set; }

        /// <summary>
        /// 判断当前设备是否处于运行状态,也就是线程还没有停止
        /// </summary>
        bool IsRuning { get; set; }

        /// <summary>
        /// 警告日志委托
        /// 为了可用性，会对异常网络进行重试。此类日志通过委托接口给出去。
        /// </summary>
        LoggerDelegate Loger { get; set; }

        /// <summary>
        /// 表示读取失败多少次以后,判断为掉线,执行断线重连程序
        /// </summary>
        int MaxErrorCount { get; set; }

        /// <summary>
        /// 一次最多读取多少个位
        /// </summary>
        int MaxReadBits { get; set; }

        /// <summary>
        /// 一次最多读取多少个字节
        /// </summary>
        int MaxReadBytes { get; set; }

        /// <summary>
        /// 设备名
        /// </summary>
        string Name { get; set; }
        /// <summary>
        /// 统计重连次数
        /// </summary>
        int ReconnectionCount { get; set; }

        /// <summary>
        /// 重连等待时间
        /// </summary>
        int ReConnectTime { get; set; }

        /// <summary>
        /// 超时时间
        /// </summary>
        int Timeout { get; set; }

        VariableNameType VariableNameType { get; set; }

        #endregion Properties

        #region Public Methods

        /// <summary>
        /// 关闭连接.调用dispose方法
        /// </summary>
        /// <returns></returns>
        Result Close();

        /// <summary>
        /// 第一次初始化:确认设备参数是否符合要求,不会调用Connect方法;
        /// <para>推荐在保存时候可以调用此方法来判断参数时候正确设置</para>
        /// <para>内部调用CheckDeviceParameters</para>
        /// <para>InitParameters</para>
        /// <para>CheckOther</para>
        /// </summary>
        /// <returns></returns>
        Result Init1();

        /// <summary>
        /// 第二次初始化
        /// <para>将设备添加到系统</para>
        /// </summary>
        /// <returns></returns>
        Result Init2();

        /// <summary>
        /// 打开连接（如果已经是连接状态会先关闭再打开）
        /// 调用connect方法,会将autoopen设置为false,就不会自动断开了
        /// </summary>
        /// <returns></returns>
        Result Open();
        /// <summary>
        /// 保存为Json格式的配置文件 : 会调用Auto里面的SaveJson方法
        /// </summary>
        /// <returns></returns>
        Result SaveJson(string path = "setting.json");

        /// <summary>
        /// 安全启动自动这台设备:会验证参数设定是否正确
        /// </summary>
        /// <returns></returns>
        Result Start(LoggerDelegate loger = null, Action<BaseVariable, AlarmEventArgs> alarmer = null, Action<BaseVariable> dataChange = null);

        /// <summary>
        /// 取消线程,并且调用close  dispose方法
        /// </summary>
        /// <returns></returns>
        Result Stop();

        /// <summary>
        /// 如果是布尔,用0和1表示;其他值,直接输入就好
        /// </summary>
        /// <param name="name"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        Task<Result> WriteAsync(string name, double value);

        #endregion Public Methods
    }
}